
import { _decorator, Component, Node, EventTouch, director } from 'cc';
import { audioManager } from './audioManager';
import eventUtil from './eventUtil';
const { ccclass, property } = _decorator;

@ccclass('BaseObject')
export class BaseObject extends Component {

    public hasName(node: Node, ...nameArray: Array<string>) {
        let has: boolean = false;
        for (let i = 0; i < nameArray.length; i++) {
            if (node.name.indexOf(nameArray[i]) != -1) {
                return true;
            }
        }
        return false;
    }

    public onDestroy() {
        eventUtil.removeAllListener(this);
    }



    private eventPool: { [name: string]: { [eventType: string]: { listeners: Array<(Function)> } } } = {};
    private addListener(node: Node, eventType: string, callback: (e: EventTouch) => void) {
        if (!this.eventPool.hasOwnProperty(node.uuid)) {
            this.eventPool[node.uuid] = {};
        }
        if (!this.eventPool[node.uuid][eventType]) {
            this.eventPool[node.uuid][eventType] = { listeners: [callback] };
        }
        else {
            this.eventPool[node.uuid][eventType].listeners.push(callback);
        }
    }
    private triggerListener(node: Node, eventType: string, e: EventTouch) {
        if (this.eventPool.hasOwnProperty(node.uuid)) {
            if (this.eventPool[node.uuid][eventType]) {
                let listeners = this.eventPool[node.uuid][eventType].listeners;
                for (let i = 0; i < listeners.length; i++) {
                    listeners[i].apply(this, [e]);
                }
            }
        }
    }
    private hasListener(node: Node, eventType: string, callback: (e: EventTouch) => void) {
        if (this.eventPool.hasOwnProperty(node.uuid)) {
            if (this.eventPool[node.uuid][eventType]) {
                let listeners = this.eventPool[node.uuid][eventType].listeners;
                for (let i = 0; i < listeners.length; i++) {
                    if (listeners[i] == callback) {
                        return true;
                    }
                }
            }
        }
        return false;
    }
    private hasEventType(node: Node, eventType: string) {
        if (this.eventPool.hasOwnProperty(node.uuid)) {
            if (this.eventPool[node.uuid][eventType] && this.eventPool[node.uuid][eventType].listeners.length > 0) {
                return true;
            }
        }
        return false;
    }
    public bindTouchStart(node: Node, callback: (event: EventTouch) => void) {
        let eventType = Node.EventType.TOUCH_START;
        node.on(eventType, callback, this)
    }
    public bindTouchMove(node: Node, callback: (e: EventTouch) => void) {
        node.on(Node.EventType.TOUCH_MOVE, callback, this)
    }
    public bindTouchEnd(node: Node, callback: (e: EventTouch) => void, soundName: string = "btnSound") {
        let eventType = Node.EventType.TOUCH_END;
        if (!this.hasEventType(node, eventType)) {
            node.on(eventType, (e: EventTouch) => {
                audioManager.playAudio(soundName);
                this.triggerListener(node, eventType, e);
            }, this)
        }

        if (!this.hasListener(node, eventType, callback)) {
            this.addListener(node, eventType, callback);
        }
    }
    public bindTouchCancel(node: Node, callback: (e: EventTouch) => void) {
        node.on(Node.EventType.TOUCH_CANCEL, callback, this)
    }

    public unbindTouchStart(node: Node, callback: (e: EventTouch) => void) {
        let eventType = Node.EventType.TOUCH_START;
        if (callback) {
            this.removeListener(node, eventType, callback);
        }
        else
            node.off(eventType)
    }
    public unbindTouchMove(node: Node, callback?: (e: EventTouch) => void) {
        node.off(Node.EventType.TOUCH_MOVE)
    }
    public unbindTouchEnd(node: Node, callback?: (e: EventTouch) => void) {
        let eventType = Node.EventType.TOUCH_END;
        if (callback) {
            this.removeListener(node, eventType, callback);
        }
        else
            node.off(eventType)
    }
    public unbindTouchCancel(node: Node, callback?: (e: EventTouch) => void) {
        node.off(Node.EventType.TOUCH_CANCEL)
    }

    private removeListener(node: Node, eventType: string, callback: (e: EventTouch) => void) {
        if (this.eventPool.hasOwnProperty(node.uuid)) {
            if (this.eventPool[node.uuid][eventType]) {
                let listeners = this.eventPool[node.uuid][eventType].listeners;
                if (callback) {
                    for (let i = 0; i < listeners.length; i++) {
                        if (listeners[i] == callback) {
                            listeners.splice(i, 1);
                            if (listeners.length == 0) {
                                node.off(eventType)
                            }
                            i--;
                        }
                    }
                }
                else {
                    this.eventPool[node.uuid][eventType].listeners = [];
                    node.off(eventType)
                }
            }
        }
        else {
            node.off(eventType);
        }
    }

    public get firstSiblingIndex(): number {
        return this.node.children.length - 1;
    }

    public isScene(sceneName: string) {
        let currentScene = director.getScene();
        if (currentScene && currentScene.name === sceneName) {
            return true;
        }
        return false;
    }
}

/**
 * [1] Class member could be defined like this.
 * [2] Use `property` decorator if your want the member to be serializable.
 * [3] Your initialization goes here.
 * [4] Your update function goes here.
 *
 * Learn more about scripting: https://docs.cocos.com/creator/3.0/manual/en/scripting/
 * Learn more about CCClass: https://docs.cocos.com/creator/3.0/manual/en/scripting/ccclass.html
 * Learn more about life-cycle callbacks: https://docs.cocos.com/creator/3.0/manual/en/scripting/life-cycle-callbacks.html
 */
